/*
 * @Author: dadadaXU 1413107032@qq.com
 * @Date: 2025-02-14 15:28:43
 * @LastEditors: dadadaXU 1413107032@qq.com
 * @LastEditTime: 2025-02-15 16:12:23
 * @FilePath: /thread-pool/ThreadPool_pro/ThreadPool.cpp
 * @Description: 升级版的线程池
 */
#include "ThreadPool.hpp"

ThreadPool::ThreadPool()
	: initThreadSize_(0), tasksSize_(0), idleThreadSize_(0), threadSizeThreshHold_(THREAD_MAX_THRESHOLD), tasksQueMaxThreshHold_(TASK_MAX_THRESHOLD), poolMode_(PoolMode::MODE_FIXED), isPoolRunning_(false)
{
}

ThreadPool::~ThreadPool()
{
	stop();
}

bool ThreadPool::checkPoolState() const
{
	return isPoolRunning_.load();
}

void ThreadPool::setMode(PoolMode mode)
{
	/* 线程池运行时无法修改 */
	if (checkPoolState())
	{
		std::cerr << "mode set failed" << std::endl;
		return;
	}
	poolMode_ = mode;
}

void ThreadPool::setTaskQueMaxThreshHold(size_t threshHold)
{
	if (threshHold > 0)
		tasksQueMaxThreshHold_ = threshHold;
}

void ThreadPool::setThreadSizeThreshHold(size_t threshHold)
{
	/* 线程池运行时无法修改 */
	if (checkPoolState())
	{
		std::cerr << "thread size set failed" << std::endl;
		return;
	}

	if (poolMode_ == PoolMode::MODE_FIXED)
		threadSizeThreshHold_ = threshHold;
}

void ThreadPool::createThread()
{
	/* 绑定线程回调函数 */
	auto thread_ptr = std::make_unique<std::thread>(
		std::bind(&ThreadPool::threadFunc, this));

	std::thread::id tid = thread_ptr->get_id(); // 在分离之前获取线程 ID
	threads_[tid] = std::move(thread_ptr);		// unique_ptr 不允许拷贝构造

	/* 在后台独自运行  detach()会导致线程对象失效 */
	threads_[tid]->detach();

#ifdef THREAD_EXECUTE_LOG
	std::cout << "Thread created\ttid:" << tid << std::endl;
#endif
	idleThreadSize_++;
}

void ThreadPool::start(size_t initThreadSize)
{
	isPoolRunning_.store(true);
	initThreadSize_ = (initThreadSize > 0) ? initThreadSize : std::thread::hardware_concurrency();

	/* 创建线程对象 */
	for (size_t i = 0; i < initThreadSize_; i++)
		createThread();
}

void ThreadPool::stop()
{
	isPoolRunning_.store(false);

	{ /* 等待线程池中的线程结束执行 */
		std::unique_lock<std::mutex> lock(tasksQueMtx_);
		notEmpty_.notify_all(); // 唤醒阻塞线程
		exitCond_.wait(lock, [&]() -> bool
					   { return threads_.empty(); });
	}

	idleThreadSize_.store(initThreadSize_);
}

void ThreadPool::threadFunc()
{
#ifdef THREAD_EXECUTE_LOG
	std::cout << "Thread start\ttid:" << std::this_thread::get_id() << std::endl;
#endif
	for (;;) /* 不断从线程池获取任务 */
	{
		Task task;

		{ /* 互斥访问任务队列 */
			std::unique_lock<std::mutex> lock(tasksQueMtx_);

			/* 等待获取任务 */
			while (tasksQue_.empty())
			{
				/* 回收线程 */
				if (!checkPoolState())
				{
					threads_.erase(std::this_thread::get_id());
					exitCond_.notify_one();
#ifdef THREAD_EXECUTE_LOG
					std::cout << "Thread exit\ttid:" << std::this_thread::get_id() << std::endl;
#endif
					return;
				}

				/* cached 模式 超时回收多余线程 */
				if (poolMode_ == PoolMode::MODE_CACHED)
				{
					if (std::cv_status::timeout ==
							notEmpty_.wait_for(lock, std::chrono::seconds(THREAD_MAX_IDLE_TIME)) &&
						threads_.size() > initThreadSize_)
					{
						/* 回收当前线程 */
						threads_.erase(std::this_thread::get_id());
#ifdef THREAD_EXECUTE_LOG
						std::cout << "Exit(cached)\ttid:" << std::this_thread::get_id() << std::endl;
#endif
						idleThreadSize_--;
						return; // 结束当前线程运行
					}
				}
				/* fixed 模式 等待任务队列有任务 */
				else
				{
					notEmpty_.wait(lock);
				}
			}

			task = tasksQue_.front();
			tasksQue_.pop();

			/* 还有剩余任务，继续通知其他线程 */
			if (!tasksQue_.empty())
				notEmpty_.notify_one();
		}

		idleThreadSize_--;
		tasksSize_--;
		notFull_.notify_one(); // 通知生产者

		/* 当前线程执行该任务 */
		if (task != nullptr)
			task(); // 执行 std::function<void()>;
			
#ifdef THREAD_EXECUTE_LOG
		std::cout << "Execute task\ttid:" << std::this_thread::get_id() << std::endl;
#endif
		/* 线程空闲 */
		idleThreadSize_++;
	}
}